#include "Lighting.glsl";
    attribute vec4 a_Position;
#ifdef GPU_INSTANCE
    attribute mat4 a_MvpMatrix;
#else
    uniform mat4 u_MvpMatrix;
#endif

#if defined(DIFFUSEMAP)||((defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT))&&(defined(SPECULARMAP)||defined(NORMALMAP)))||(defined(LIGHTMAP)&&defined(UV))
    attribute vec2 a_Texcoord0;
    varying vec2 v_Texcoord0;
#endif

#if defined(LIGHTMAP)&&defined(UV1)
    attribute vec2 a_Texcoord1;
#endif

#ifdef LIGHTMAP
    uniform vec4 u_LightmapScaleOffset;
    varying vec2 v_LightMapUV;
#endif

#ifdef COLOR
    attribute vec4 a_Color;
    varying vec4 v_Color;
#endif

#ifdef BONE
    const int c_MaxBoneCount = 24;
    attribute vec4 a_BoneIndices;
    attribute vec4 a_BoneWeights;
    uniform mat4 u_Bones[c_MaxBoneCount];
#endif

attribute vec3 a_Normal;
varying vec3 v_Normal; 
#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)
    uniform vec3 u_CameraPos;
    varying vec3 v_ViewDir; 
#endif

#if defined(NORMALMAP)
    attribute vec4 a_Tangent0;
    varying vec3 v_Tangent;
    varying vec3 v_Binormal;
#endif

#ifdef GPU_INSTANCE
    attribute mat4 a_WorldMat;
#else
    uniform mat4 u_WorldMat;
#endif

#if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)||defined(RECEIVESHADOW)
    varying vec3 v_PositionWorld;
#endif
varying float v_posViewZ;
#ifdef RECEIVESHADOW
    #ifdef SHADOWMAP_PSSM1 
        varying vec4 v_lightMVPPos;
        uniform mat4 u_lightShadowVP[4];
    #endif
#endif
#ifdef TILINGOFFSET
    uniform vec4 u_TilingOffset;
#endif

void main_castShadow(){
    vec4 position;
    #ifdef BONE
        mat4 skinTransform = u_Bones[int(a_BoneIndices.x)] * a_BoneWeights.x;
        skinTransform += u_Bones[int(a_BoneIndices.y)] * a_BoneWeights.y;
        skinTransform += u_Bones[int(a_BoneIndices.z)] * a_BoneWeights.z;
        skinTransform += u_Bones[int(a_BoneIndices.w)] * a_BoneWeights.w;
        position=skinTransform*a_Position;
    #else
        position=a_Position;
    #endif
    #ifdef GPU_INSTANCE
        gl_Position = a_MvpMatrix * position;
        #else
    gl_Position = u_MvpMatrix * position;
    #endif
    //TODO没考虑UV动画呢
    #if defined(DIFFUSEMAP)&&defined(ALPHATEST)
        v_Texcoord0=a_Texcoord0;
    #endif
        gl_Position=remapGLPositionZ(gl_Position);
    v_posViewZ = gl_Position.z;
}

void main_normal()
{
    vec4 position;
    #ifdef BONE
        mat4 skinTransform = u_Bones[int(a_BoneIndices.x)] * a_BoneWeights.x;
        skinTransform += u_Bones[int(a_BoneIndices.y)] * a_BoneWeights.y;
        skinTransform += u_Bones[int(a_BoneIndices.z)] * a_BoneWeights.z;
        skinTransform += u_Bones[int(a_BoneIndices.w)] * a_BoneWeights.w;
        position=skinTransform*a_Position;
    #else
        position=a_Position;
    #endif

    #ifdef GPU_INSTANCE
        gl_Position = a_MvpMatrix * position;
    #else
        gl_Position = u_MvpMatrix * position;
    #endif

    mat4 worldMat;
    #ifdef GPU_INSTANCE
        worldMat = a_WorldMat;
    #else
        worldMat = u_WorldMat;
    #endif

    mat3 worldInvMat;
    #ifdef BONE
        worldInvMat=inverseMat(mat3(worldMat*skinTransform));
    #else
        worldInvMat=inverseMat(mat3(worldMat));
    #endif  

    v_Normal=normalize(a_Normal*worldInvMat);
    #if defined(NORMALMAP)
        v_Tangent=normalize(a_Tangent0.xyz*worldInvMat);
        v_Binormal=cross(v_Normal,v_Tangent)*a_Tangent0.w;
    #endif
    #if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)||defined(RECEIVESHADOW)
        v_PositionWorld=(worldMat*position).xyz;
    #endif
    #if defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT)
        v_ViewDir=u_CameraPos-v_PositionWorld;
    #endif

    #if defined(DIFFUSEMAP)||((defined(DIRECTIONLIGHT)||defined(POINTLIGHT)||defined(SPOTLIGHT))&&(defined(SPECULARMAP)||defined(NORMALMAP)))
        #ifdef TILINGOFFSET
            v_Texcoord0=TransformUV(a_Texcoord0,u_TilingOffset);
        #else
            v_Texcoord0=a_Texcoord0;
        #endif
    #endif
    #ifdef LIGHTMAP
        #ifdef UV1
            v_LightMapUV=vec2(a_Texcoord1.x,1.0-a_Texcoord1.y)*u_LightmapScaleOffset.xy+u_LightmapScaleOffset.zw;
        #else
            v_LightMapUV=vec2(a_Texcoord0.x,1.0-a_Texcoord0.y)*u_LightmapScaleOffset.xy+u_LightmapScaleOffset.zw;
        #endif 
        v_LightMapUV.y=1.0-v_LightMapUV.y;
    #endif

    #if defined(COLOR)&&defined(ENABLEVERTEXCOLOR)
        v_Color=a_Color;
    #endif
    #ifdef RECEIVESHADOW
        v_posViewZ = gl_Position.w;
        #ifdef SHADOWMAP_PSSM1
        v_lightMVPPos = u_lightShadowVP[0] * vec4(v_PositionWorld,1.0);
        #endif
    #endif
    gl_Position=remapGLPositionZ(gl_Position);
}
    

void main()
{
    #ifdef CASTSHADOW
        main_castShadow();
    #else
        main_normal();
    #endif
}